#![allow(unused_imports)]
use crate::domain::UserBean;
use crate::{
	domain::error::{Error as SysError, Result},
};
use sqlx::Error;

use jsonwebtoken::DecodingKey;
use crate::utils::jwt_util::JWT_SECRET;
use jsonwebtoken::Validation;
use crate::utils::jwt_util::Claims;

use crate::serviceimpl::user_service::find_user_shadow_by_user_name;
use crate::serviceimpl::user_service::find_user_by_id;
use crate::serviceimpl::user_service::list_active_user_roles_using_user_id;
use crate::serviceimpl::role_service::list_active_role_permissions_using_role_id;
use crate::domain::RoleBean;
use crate::domain::PermissionBean;

use regex::Regex;
use crate::utils::encrypt_util::verify_password;

pub async fn can_access(token:String, path:String) -> bool{
	if path.contains("/login/") || path.contains("/loginController/") {
		return true;
	}else if String::len(&token) == 0 {
		return false;
	}else{
		let claims:Claims = jsonwebtoken::decode(
			&token,
			&DecodingKey::from_secret(JWT_SECRET.as_bytes()),
			&Validation::default(),
		)
		.map(|data| data.claims).unwrap();
		let user = find_user_by_id(claims.sub).await.unwrap();
		let roles = list_active_user_roles_using_user_id(user.id).await.unwrap();
		let mut permissions = Vec::<PermissionBean>::new();
		for role in &roles {
			let mut sub_privs = list_active_role_permissions_using_role_id(role.id).await.unwrap();
			permissions.append(&mut sub_privs);
		}
		if contains_role(roles,"admin".to_string()) {
			true
		}else{
			contains_all_permission(permissions, path)
		}
	}
}

pub fn contains_role(roles:Vec<RoleBean>,role_name:String)->bool{
	let mut contains = false;
	for role in roles {
		if role.role_name == role_name {
			contains = true;
		}
	}
	contains
}

pub fn contains_permission(permissions:Vec<PermissionBean>,perm_name:String)->bool{
	let mut contains = false;
	for permission in permissions {
		if permission.perm_name == perm_name {
			contains = true;
		}
	}
	contains
}

pub fn contains_all_permission(privs:Vec<PermissionBean>,uri:String) -> bool {
	let require_privs = get_perms_by_path(uri);
	if require_privs.get(0).unwrap() == &"annon" || require_privs.get(0).unwrap() == &"authc" {
		return true;
	} else if require_privs.get(0).unwrap() == &"noauth"{
		return false;
	} else  if privs.len() == 0 {
		return false;
	} else {
		for permission in require_privs {
			if !contains_permission(privs.clone(),permission) {
				return false;
			}
		}
		true
	}
}

fn get_perms_by_path(path:String) -> Vec<String>{
	if path == "/".to_string() {
		return  vec!["annon".to_string()];
	}
	if path == "/favicon.ico".to_string() {
		return  vec!["annon".to_string()];
	}
	if path == "/pages/".to_string() {
		return  vec!["annon".to_string()];
	}
	if path == "/index.html".to_string() {
		return  vec!["annon".to_string()];
	}

	if path.starts_with("/images/"){
		return  vec!["annon".to_string()];
	}

	if path.starts_with("/js/") {
		return  vec!["annon".to_string()];
	}

	if path.starts_with("/easyui/") {
		return  vec!["annon".to_string()];
	}

	if path.starts_with("/echarts/"){
		return  vec!["annon".to_string()];
	}

	if path.starts_with("/uploadjs/"){
		return  vec!["annon".to_string()];
	}

	if path == "/login/index.html" {
		return  vec!["annon".to_string()];
	}

	if path == "/login/register.html" {
		return  vec!["annon".to_string()];
	}

	if  path == "/login/error.html" {
		return  vec!["annon".to_string()];
	}

	if  path == "/login/noauth.html" {
		return  vec!["annon".to_string()];
	}

	if  path == "/pages/index.html"{
		return  vec!["authc".to_string()];
	}

	if path.starts_with("/loginController/") {
		return  vec!["authc".to_string()];
	}

	if path.starts_with("/profileController/") {
		return  vec!["authc".to_string()];
	}

	let re = Regex::new(r"/*Controller/find*").unwrap();
	if re.is_match(&path){
		return  vec!["authc".to_string()];
	}

	let re2 = Regex::new(r"/*Controller/listActive*").unwrap();
	if re2.is_match(&path){
		return  vec!["authc".to_string()];
	}

	let re3 = Regex::new(r"/*Controller/listAll*").unwrap();
	if re3.is_match(&path){
		return  vec!["authc".to_string()];
	}
	
	if path == "/pages/custorders.html" {
		return  vec!["CustOrder".to_string()];
	}
	
	if path.starts_with("/custOrderController/") {
		return  vec!["CustOrder".to_string()];
	}
	
	if path == "/pages/goodses.html" {
		return  vec!["Goods".to_string()];
	}
	
	if path.starts_with("/goodsController/") {
		return  vec!["Goods".to_string()];
	}
	
	if path == "/pages/goodstypes.html" {
		return  vec!["GoodsType".to_string()];
	}
	
	if path.starts_with("/goodsTypeController/") {
		return  vec!["GoodsType".to_string()];
	}
	
	if path == "/pages/orderitems.html" {
		return  vec!["OrderItem".to_string()];
	}
	
	if path.starts_with("/orderItemController/") {
		return  vec!["OrderItem".to_string()];
	}
	
	if path == "/pages/paytypes.html" {
		return  vec!["PayType".to_string()];
	}
	
	if path.starts_with("/payTypeController/") {
		return  vec!["PayType".to_string()];
	}
	
	if path == "/pages/recommends.html" {
		return  vec!["Recommend".to_string()];
	}
	
	if path.starts_with("/recommendController/") {
		return  vec!["Recommend".to_string()];
	}
	
	if path == "/pages/statuses.html" {
		return  vec!["Status".to_string()];
	}
	
	if path.starts_with("/statusController/") {
		return  vec!["Status".to_string()];
	}
	
	return  vec!["noauth".to_string()];
}

pub async fn login_user(user_name:String,password:String) ->Result<UserBean> {
	let user = find_user_shadow_by_user_name(user_name).await?;
	if verify_password(password, user.salt.clone(), user.password.clone()).await? {
		Ok(user.clone())
	} else {
		Err(SysError::WrongPassword)
	}
}

